/**
 * Notes: passport模块业务逻辑 
 * Date: 2020-10-14 07:48:00 
 * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY cclinux0730 (wechat)
 */

const BaseProjectService = require('./base_project_service.js');
const cloudBase = require('../../../framework/cloud/cloud_base.js');
const UserModel = require('../config/models_config').user_model;
const WhiteModel = require('../config/models_config').white_model;
const dataUtil = require('../../../framework/helpers/data_util.js');

class PassportService extends BaseProjectService {

	// 注册
	async register(userId, {
		mobile,
		name,
		forms,
		status,
		password
	}) {
		try {
			console.log('[register] 开始注册处理:', {userId, mobile, name});
			
			// 白名单验证
			mobile = mobile.trim();
			name = name.trim();
			
			// 白名单验证 - 首先尝试精确匹配
			let white = await WhiteModel.getOne({ 
				WHITE_TITLE: mobile, 
				WHITE_NAME: name 
			});
			
			// 仅在管理员指定的模式下允许模糊匹配
			// 注意：一般情况下应该严格匹配，这里保留后备验证以防特殊情况
			if (!white && process.env.ALLOW_FUZZY_WHITELIST === 'true') {
				console.log('[register] 精确匹配失败，尝试模糊匹配 (管理员允许模式)');
				white = await WhiteModel.getOne({ WHITE_TITLE: mobile });
				
				// 如果找到记录但姓名不匹配，报错
				if (white && white.WHITE_NAME !== name) {
					console.error('[register] 手机号存在于白名单但姓名不匹配:', {
						expected: white.WHITE_NAME,
						actual: name,
						mobile: mobile
					});
					this.AppError(`该手机号已绑定姓名"${white.WHITE_NAME}"，请使用该姓名或联系管理员`);
				}
			}
			
			// 如果白名单检查失败
			if (!white) {
				console.error('[register] 白名单验证失败:', {mobile, name});
				this.AppError('该手机+姓名未在白名单中，请修改或者联系管理员');
			}
			
			console.log('[register] 白名单验证通过:', {mobile, name, dept: white.WHITE_DEPT});

			// 判断是否存在
			let where = {
				USER_MINI_OPENID: userId
			}
			let cnt = await UserModel.count(where);
			if (cnt > 0) {
				console.log('[register] 用户已存在，直接登录');
				return await this.login(userId);
			}

			where = {
				USER_MOBILE: mobile
			}
			cnt = await UserModel.count(where);
			if (cnt > 0) {
				console.error('[register] 手机号已被注册:', mobile);
				this.AppError('该手机已注册');
			}

			// 构造简单的用户数据，避免复杂处理
			try {
				// 提取职位和工号
				let positionVal = '', noVal = '';
				if (Array.isArray(forms)) {
					for (let item of forms) {
						if (item.mark === 'zhiwu') positionVal = item.val || '';
						if (item.mark === 'no') noVal = item.val || '';
					}
				}
				
				// 规范化表单数据
				let validForms = [];
				if (Array.isArray(forms)) {
					validForms = forms.map(item => {
						return {
							mark: item.mark || '',
							title: item.title || '',
							type: item.type || 'text',
							val: (item.val === undefined || item.val === null) ? '' : String(item.val).trim()
						};
					});
				}
				
				// 直接使用白名单信息创建用户，包含表单数据
				let data = {
					USER_MINI_OPENID: userId,
					USER_MOBILE: mobile,
					USER_NAME: name,
					USER_DEPT: white.WHITE_DEPT || '',
					USER_TITLE: positionVal,
					USER_NO: noVal,
					USER_FORMS: validForms,  // 恢复表单数据存储
					USER_STATUS: Number(status) || 1,
					USER_ADD_TIME: this._timestamp,
					USER_LOGIN_CNT: 1,
					USER_LOGIN_TIME: this._timestamp,
					USER_PASSWORD: password || mobile.slice(-6)
				};
				
				console.log('[register] 准备插入数据:', data);
				
				// 避免数据库类型错误
				for (let key in data) {
					if (data[key] === undefined || data[key] === null) {
						if (typeof data[key] === 'string') data[key] = '';
						else if (typeof data[key] === 'number') data[key] = 0;
						else if (Array.isArray(data[key])) data[key] = [];
						else if (typeof data[key] === 'object') data[key] = {};
					}
				}
				
				console.log('[register] 使用safeInsert插入数据');
				await UserModel.safeInsert(data);
				console.log('[register] 数据插入成功');

				return await this.login(userId);
			} catch (e) {
				console.error('[register] 处理用户数据异常:', e);
				
				// 如果包含脏数据，尝试特别处理
				if (e.message && e.message.includes('脏数据')) {
					console.log('[register] 检测到脏数据错误，尝试使用最小化数据创建用户');
					
					// 使用最小化数据创建用户
					let minData = {
						USER_MINI_OPENID: userId,
						USER_MOBILE: mobile,
						USER_NAME: name,
						USER_DEPT: white.WHITE_DEPT || '',
						USER_STATUS: 1,
						USER_FORMS: [],  // 空表单，但保留字段
						USER_ADD_TIME: this._timestamp,
						USER_LOGIN_TIME: this._timestamp,
						USER_PASSWORD: mobile.slice(-6)
					};
					
					try {
						await UserModel.safeInsert(minData);
						console.log('[register] 最小化数据插入成功');
						return await this.login(userId);
					} catch (err) {
						console.error('[register] 最小化数据插入也失败:', err);
						// 返回明确的错误信息，便于排查
						if (err.message) {
							this.AppError('注册失败: ' + err.message);
						} else {
							this.AppError('注册失败，请联系管理员');
						}
					}
				} else {
					this.AppError('注册失败: ' + (e.message || '数据异常，请联系管理员'));
				}
			}
		} catch (err) {
			console.error('[register] 注册异常:', err);
			
			// 防止脏数据错误传递到前端
			if (err.message && err.message.includes('脏数据')) {
				this.AppError('注册失败，系统处理异常，请联系管理员');
			} else {
				throw err; // 其他错误正常抛出
			}
		}
	}

	/** 获取手机号码 */
	async getPhone(cloudID) {
		let cloud = cloudBase.getCloud();
		let res = await cloud.getOpenData({
			list: [cloudID], // 假设 event.openData.list 是一个 CloudID 字符串列表
		});
		if (res && res.list && res.list[0] && res.list[0].data) {
			let phone = res.list[0].data.phoneNumber;
			return phone;
		} else
			return '';
	}

	/** 取得我的用户信息 */
	async getMyDetail(userId) {
		if (!userId) {
			console.log('[getMyDetail] 未提供用户ID，返回空数据');
			return {}; // 用户未登录，返回空对象
		}

		let where = {
			USER_MINI_OPENID: userId
		}
		let fields = 'USER_DEPT,USER_MOBILE,USER_NAME,USER_FORMS,USER_OBJ,USER_STATUS,USER_CHECK_REASON,USER_AUTH,USER_TITLE,USER_NO';
		
		try {
			let user = await UserModel.getOne(where, fields);
			if (!user) {
				console.log('[getMyDetail] 用户不存在:', userId);
				return {}; // 用户不存在，返回空对象而不是null
			}
			
			console.log('[getMyDetail] 成功获取用户信息:', userId);
			return user;
		} catch (err) {
			console.error('[getMyDetail] 查询用户信息出错:', err);
			return {}; // 出错时也返回空对象，保持一致性
		}
	}

	/** 修改用户资料 */
	async editBase(userId, {
		mobile,
		name,
		forms
	}) {
		// 白名单验证
		let white = await WhiteModel.getOne({ WHITE_TITLE: mobile, WHITE_NAME: name });
		if (!white) this.AppError('该手机+姓名未在白名单中，请修改或者联系管理员');

		let whereMobile = {
			USER_MOBILE: mobile,
			USER_MINI_OPENID: ['<>', userId]
		}
		let cnt = await UserModel.count(whereMobile);
		if (cnt > 0) this.AppError('该手机已注册');

		let where = {
			USER_MINI_OPENID: userId
		}

		let user = await UserModel.getOne(where);
		if (!user) return;

		// 处理表单数据
		let userObj = dataUtil.dbForms2Obj(forms);

		let data = {
			USER_MOBILE: mobile,
			USER_NAME: name,
			USER_DEPT: white.WHITE_DEPT || userObj['所属部门'] || user.USER_DEPT || '',
			USER_TITLE: userObj['职位'] || user.USER_TITLE || '',
			USER_NO: userObj['工号'] || user.USER_NO || '',
			USER_OBJ: userObj,
			USER_FORMS: forms,
		};

		if (user.USER_STATUS == UserModel.STATUS.UNCHECK)
			data.USER_STATUS = UserModel.STATUS.UNUSE;

		await UserModel.edit(where, data);
	}

	/** 登录 */
	async login(name, pwd) {
		try {
			console.log('[login] 开始使用姓名和密码登录:', name);
			
			if (!name) {
				this.AppError('姓名不能为空');
			}
			
			if (!pwd) {
				this.AppError('密码不能为空');
			}
			
			// 查询用户
			let where = {
				USER_NAME: name
			};
			
			let user = await UserModel.getOne(where);
			if (!user) {
				this.AppError('该用户不存在');
			}
			
			// 密码验证
			if (!user.USER_PASSWORD || user.USER_PASSWORD !== pwd) {
				this.AppError('密码错误');
			}
			
			// 用户状态检查
			if (user.USER_STATUS === UserModel.STATUS.UNUSE) {
				this.AppError('该用户未启用');
			}
			
			if (user.USER_STATUS === UserModel.STATUS.UNCHECK) {
				this.AppError('该用户待审核');
			}
			
			// 更新登录时间和次数
			let dataUpdate = {
				USER_LOGIN_TIME: this._timestamp
			};
			await UserModel.edit(where, dataUpdate);
			await UserModel.inc(where, 'USER_LOGIN_CNT', 1);
			
			// 组装token数据
			let token = {};
			token.id = user.USER_MINI_OPENID;
			token.key = user.USER_ID;
			token.name = user.USER_NAME;
			token.dept = user.USER_DEPT;
			token.status = user.USER_STATUS;
			token.phone = user.USER_MOBILE;
			token.title = user.USER_TITLE;
			token.no = user.USER_NO;
			
			console.log('[login] 用户登录成功:', {
				USER_NAME: user.USER_NAME,
				USER_MOBILE: user.USER_MOBILE
			});
			
			return {
				token
			};
		} catch (err) {
			console.error('[login] 登录失败:', err);
			throw err;
		}
	}

	/** 通过openid登录 */
	async loginByOpenId(userId) {
		let where = {
			'USER_MINI_OPENID': userId
		};
		let fields = 'USER_DEPT,USER_ID,USER_MINI_OPENID,USER_NAME,USER_MOBILE,USER_STATUS,USER_TITLE,USER_NO';
		let user = await UserModel.getOne(where, fields);
		let token = {};
		if (user) {
			// 正常用户
			token.id = user.USER_MINI_OPENID;
			token.key = user.USER_ID;
			token.name = user.USER_NAME;
			token.dept = user.USER_DEPT;
			token.status = user.USER_STATUS;
			token.phone = user.USER_MOBILE;
			token.title = user.USER_TITLE;
			token.no = user.USER_NO;

			// 异步更新最近更新时间
			let dataUpdate = {
				USER_LOGIN_TIME: this._timestamp
			};
			UserModel.edit(where, dataUpdate);
			UserModel.inc(where, 'USER_LOGIN_CNT', 1);

		} else
			token = null;

		return {
			token
		};
	}

	/** 根据手机号码查询用户 */
	async getUserByMobile(mobile) {
		let where = {
			USER_MOBILE: mobile
		}
		let user = await UserModel.getOne(where);
		return user;
	}

	/** 重置密码 */
	async resetPassword(mobile, newPassword) {
		try {
			console.log('[resetPassword] 开始重置密码:', mobile);
			
			// 参数校验
			if (!mobile) {
				this.AppError('手机号不能为空');
			}
			
			if (!newPassword) {
				this.AppError('新密码不能为空');
			}
			
			if (newPassword.length < 6) {
				this.AppError('密码长度不能少于6位');
			}
			
			// 查询用户
			let where = {
				USER_MOBILE: mobile
			};
			
			let user = await UserModel.getOne(where);
			if (!user) {
				this.AppError('该手机号未注册');
			}
			
			// 执行密码更新
			let data = {
				USER_PASSWORD: newPassword,
				USER_LOGIN_TIME: this._timestamp
			};
			
			await UserModel.edit(where, data);
			
			console.log('[resetPassword] 密码重置成功:', mobile);
			
			return true;
		} catch (err) {
			console.error('[resetPassword] 密码重置失败:', err);
			throw err;
		}
	}

	/** 检查用户是否在白名单中 */
	async check_whitelist(name, mobile) {
		try {
			console.log('[check_whitelist] 检查白名单:', name, mobile);
			
			// 验证输入参数
			if (!name || !mobile) {
				console.error('[check_whitelist] 参数不完整:', {name, mobile});
				return {
					result: false
				};
			}
			
			// 确保手机号格式正确
			if (mobile.length != 11) {
				console.error('[check_whitelist] 手机号格式不正确:', mobile);
				return {
					result: false
				};
			}
			
			// 查询白名单记录
			let white = await WhiteModel.getOne({ 
				WHITE_TITLE: mobile, 
				WHITE_NAME: name 
			});
			
			console.log('[check_whitelist] 查询结果:', white ? '找到记录' : '未找到记录');
			
			// 返回结果
			return {
				result: white ? true : false,
				dept: white ? white.WHITE_DEPT : ''
			};
		} catch (err) {
			console.error('[check_whitelist] 检查白名单出错:', err);
			// 不抛出异常，返回错误结果
			return {
				result: false,
				error: '白名单检查过程出错'
			};
		}
	}

	/** 通过手机号和密码登录 */
	async loginWithPassword(mobile, password) {
		try {
			console.log('[loginWithPassword] 开始使用手机号和密码登录:', mobile);
			
			if (!mobile) {
				this.AppError('手机号不能为空');
			}
			
			if (!password) {
				this.AppError('密码不能为空');
			}
			
			// 查询用户
			let where = {
				USER_MOBILE: mobile
			};
			
			let user = await UserModel.getOne(where);
			if (!user) {
				this.AppError('该手机号未注册');
			}
			
			// 密码验证
			if (!user.USER_PASSWORD || user.USER_PASSWORD !== password) {
				this.AppError('密码错误');
			}
			
			// 用户状态检查
			if (user.USER_STATUS === UserModel.STATUS.UNUSE) {
				this.AppError('该用户未启用');
			}
			
			if (user.USER_STATUS === UserModel.STATUS.UNCHECK) {
				this.AppError('该用户待审核');
			}
			
			// 更新登录时间和次数
			let dataUpdate = {
				USER_LOGIN_TIME: this._timestamp
			};
			await UserModel.edit(where, dataUpdate);
			await UserModel.inc(where, 'USER_LOGIN_CNT', 1);
			
			// 组装token数据
			let token = {};
			token.id = user.USER_MINI_OPENID;
			token.key = user.USER_ID;
			token.name = user.USER_NAME;
			token.dept = user.USER_DEPT;
			token.status = user.USER_STATUS;
			token.phone = user.USER_MOBILE;
			token.title = user.USER_TITLE;
			token.no = user.USER_NO;
			
			console.log('[loginWithPassword] 用户登录成功:', {
				USER_NAME: user.USER_NAME,
				USER_MOBILE: user.USER_MOBILE
			});
			
			return {
				token
			};
		} catch (err) {
			console.error('[loginWithPassword] 登录失败:', err);
			throw err;
		}
	}
}

module.exports = PassportService;